checkRevoker() {
    # 如果 $0 是符号链接，则解析到实际路径
    if [ -L "$0" ]; then
        # 使用 readlink -f 在 Linux 上解析符号链接，或在 macOS 上使用 stat
        if command -v readlink >/dev/null 2>&1; then
            # 对于支持 -f 选项的 readlink（如 Linux）
            SCRIPT_PATH=$(readlink -f "$0");
        elif command -v stat >/dev/null 2>&1; then
            # 对于 macOS，readlink 没有 -f 选项，但可以使用 stat
            TARGET_PATH=$(stat -f%N "$0");
            while [ -h "$TARGET_PATH" ]; do
                TARGET_PATH=$(stat -f%Y "$TARGET_PATH");
            done;
            SCRIPT_PATH=$TARGET_PATH;
        else
            echo "Error: Unable to resolve symbolic link" >&2;
            return 1;
        fi;
    else
        # 如果 $0 不是符号链接，则直接使用 pwd 和 dirname 获取绝对路径
        SCRIPT_PATH=$(cd "$(dirname "$0")" && pwd)/$(basename "$0");
    fi;

    echo "$SCRIPT_PATH";
}

checkIpAddress() {
    local ipAddress;
  
    # 尝试使用 ip 命令（Linux）  
    if command -v ip >/dev/null 2>&1; then  
        # 获取第一个非本地回环的IPv4地址  
        ipAddress=$(ip -4 addr show scope global | grep inet | awk '{print $2}' | cut -d/ -f1 | head -n 1);
    # 如果 ip 命令不可用，则尝试使用 ifconfig 命令（macOS）  
    elif command -v ifconfig >/dev/null 2>&1; then  
        # 获取第一个非本地回环的IPv4地址  
        ipAddress=$(ifconfig | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | head -n 1);
    else  
        echo "Error: Unable to find ip or ifconfig command." >&2;
        return 1;
    fi;
  
    # 去除可能的空格和换行符  
    ipAddress=$(echo "${ipAddress}" | sed 's/^[ \t]*//;s/[ \t]*$//');
  
    # 如果找到了IP地址，则返回它  
    if [[ -n "${ipAddress}" ]]; then  
        echo "${ipAddress}";
    else  
        echo "Error: Unable to find a valid IP address." >&2;
        return 1;
    fi;
};

checkUser() {
    # 优先使用$USER环境变量，因为它在许多系统中都可用
    local user="${USER}";

    # 如果$USER为空，则使用whoami命令
    if [[ -z "$user" ]]; then
        user=$(whoami);
    fi;

    # 返回当前用户
    echo "$user";
}



function logger () {
    #日志内容
    local message=${1:-''};
    #日志级别
    local level=${2:-info};
    #时间戳
    local timestamp=$(date "+%Y-%m-%d %H:%M:%S");
    local datestamp=$(date "+%Y-%m-%d");
    #当前IP、用户、调用脚本
    local revoker=$(checkRevoker);
    local ipAddress=$(checkIpAddress);
    local user=$(checkUser);

    echo -e "[${level^^}][${timestamp}][${revoker}][${ipAddress}][${user}] ${message}";
}


function sshCheck() {

    logger "Verify SSH security free.";
    host=${1:-${host}};
    user=${2:-${user}};
    if [[ ! "${host}" ]]; then logger "Param [host] is not found."; return 1; fi;
    if [[ ! "${user}" ]]; then logger "Param [user] is not found."; return 1; fi;
    #是否执行
    #能否执行
    #执行，验证SSH免密
    set +e #在执行远程命令前;
    if [[ ! `timeout 10s ssh ${user}@${host} hostname` ]]; then
        logger "SSH free encryption not established.";
        return 1;
    fi;
    logger "SSH security free has been established.";
    set -e #在执行远程命令后;
    return 0;
}


function clean () {

    local trash=$1;
    local trashname=${trash##*/};
    local timestamp=$(date "+%Y-%m-%d-%H-%M-%S");
    local trashbin=${2:-/tmp/trashbin-${timestamp}};
    mkdir -p ${trashbin};

    if [[ -e ${trash} ]];
        then
            #echo "mv -f ${trash} ${trashbin}"
            mv -f ${trash} ${trashbin} > /dev/null 2>&1;
        else
            echo "${trash} not exist.";
    fi;
}

function listVarNames() {
    local varNames=$(while read -r line; do sed -n -E 's/^([_0-9a-zA-Z]+)=.*/\1/p'; done < <(set));
    echo ${varNames};
}

function listEnvVarNames() {
    local varNames=$(while read -r line; do sed -n -E 's/^([_0-9a-zA-Z]+)=.*/\1/p'; done < <(env));
    echo ${varNames};
}

function listFunctionNames() {
    local functionNames=$(typeset -f | sed -n -E 's/([0-9_a-zA-Z]+)[[:blank:]]*\([[:blank:]]*\).*/\1/p');
    echo ${functionNames};
}

function exportFunctions() {
    local functionNames=${1:-$(listFunctionNames)};
    for functionName in ${functionNames}; do export -f ${functionName}; done;
}

function packAssignmentCmds(){
    local varNames;
    local assignmentCmds;
    if [ -n "$1" ]; then varNames="$1"; else varNames=$(listVarNames); fi;
    for varName in ${varNames}; do
        assignmentCmds="${varName}"'='"'${!varName}'"';'"${assignmentCmds}";
    done;
    echo ${assignmentCmds} ;
}

function packExportCmds(){
    local varNames;
    local exportCmds;
    if [ -n "$1" ]; then varNames="$1"; else varNames=$(listEnvVarNames); fi;
    for varName in ${varNames}; do  exportCmds='export '${varName}';'"${exportCmds}"; done;
    echo ${exportCmds} ;
}

function packFunctionDefs(){
    local functionNames;
    local functionDefs;
    if [ -n "$1" ]; then functionNames="$1"; else functionNames=$(listFunctionNames); fi;
    for functionName in ${functionNames}; do
        functionDef=$(typeset -f ${functionName})
        functionDef="${functionDef:0:-1}"';}'
        functionDefs="function ${functionDef}"';'"${functionDefs}" ;
    done;
    echo ${functionDefs};
}

function echoRed() {
    echo -e "${BRed}$1${ColorOff}$2";
}

function echoGreen() {
    echo -e "${BGreen}$1${ColorOff}$2";
}

function echoYellow() {
    echo -e "${BYellow}$1${ColorOff}$2";
}

exportFunctions


#packExportCmds "BGreen ColorOff"
#packAssignmentCmds "BGreen ColorOff"
#packFunctionDefs "echoGreen"
#ssh opr@106.15.139.127 "$(packExportCmds "BGreen ColorOff")  $(packAssignmentCmds "BGreen ColorOff") $(packFunctionDefs "echoGreen")  echoGreen 123 "
#ssh opr@106.15.139.127 "$(packFunctionDefs "listEnvVarNames")  listEnvVarNames"


